#include "usersettings.h"
#include "globaltype.h"
#include "utils/stringutils.h"
#include "utils/utils.h"
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QStandardPaths>

#ifdef Q_OS_MAC
static constexpr const char* UPGRADE_URL = "http://partsup.top:9900/cloud/open/yingcepacks_mac.xml";
#else
static constexpr const char* UPGRADE_URL = "http://partsup.top:9900/cloud/open/yingcepacks.xml";
#endif

UserSettings::UserSettings() : upgrade_url_(UPGRADE_URL), access_dir_(QDir::home())
{
    load();
}

UserSettings& UserSettings::instance()
{
    static UserSettings inst;
    return inst;
}

ServiceUrls UserSettings::serviceUrls() const
{
    if (env_ == yc::PROD_ENV_TYPE) {
        return ServiceUrls {
            "http://partsup.top:9900/users",      "http://partsup.top:9900/auth",
            "http://partsup.top:9900/cloud",      "http://partsup.top:9900/cloud/open",
            "http://partsup.top:9900/presenters", "http://partsup.top:9900/attentions",
            "http://partsup.top:9900/lives",      "http://partsup.top:9900/records",
            "http://partsup.top:9900/platforms"
        };
    } else if (env_ == yc::DEV_ENV_TYPE) {
        return ServiceUrls { "http://localhost:9900/users",      "http://localhost:9900/auth",
                             "http://localhost:9900/cloud",      "http://localhost:9900/cloud/open",
                             "http://localhost:9900/presenters", "http://localhost:9900/attentions",
                             "http://localhost:9900/lives",      "http://localhost:9900/records",
                             "http://localhost:9900/platforms" };
    } else {
        return ServiceUrls { "http://localhost:9900/users",      "http://localhost:9900/auth",
                             "http://localhost:9900/cloud",      "http://localhost:9900/cloud/open",
                             "http://localhost:9900/presenters", "http://localhost:9900/attentions",
                             "http://localhost:9900/lives",      "http://localhost:9900/records",
                             "http://localhost:9900/platforms" };
    }
}

QDir UserSettings::resDir()
{
    QDir dir(cacheDir());
    if (dir.exists("res") || dir.mkdir("res")) {
        dir.cd("res");
        return dir;
    } else {
        return QDir::temp();
    }
}

QDir UserSettings::tempDir()
{
    QDir dir(cacheDir());
    if (dir.exists("temp") || dir.mkdir("temp")) {
        dir.cd("temp");
        return dir;
    } else {
        return QDir::temp();
    }
}

void UserSettings::load()
{
    QFile file(rootDir().absoluteFilePath("yingce.dat"));
    if (!file.open(QFile::ReadOnly)) {
        cache_dir_ = rootDir();
        recorder_settings_.video_save_dir = utils::createDirectoryInNonSystemDrive("YingceVideos");
        new_recorder_settings_.video_save_dir = recorder_settings_.video_save_dir;
        screen_capture_settings_.save_dir =
                utils::createDirectoryInNonSystemDrive("YingceScreenVideos");
        return;
    }

    const QByteArray json = file.readAll();
    file.close();

    const QJsonObject jo = QJsonDocument::fromJson(json).object();

    // 检查版本
    if (jo["version"].toInt(0) != VERSION_NUMBER) {
        recorder_settings_.video_save_dir = utils::createDirectoryInNonSystemDrive("YingceVideos");
        new_recorder_settings_.video_save_dir = recorder_settings_.video_save_dir;
        screen_capture_settings_.save_dir =
                utils::createDirectoryInNonSystemDrive("YingceScreenVideos");
        return;
    }

    disclaimer_accepted_ = jo["disclaimerAccepted"].toBool(false);
    // Updater
    ignore_major_version_ = jo["ignoreMajorVersion"].toString();
    ignore_update_date_ = jo["ignoreUpdateDate"].toString();
    login_user_.updateData(jo["lastLoginUser"].toObject());
    // Window state
    window_state_ = jo["windowState"].toInt();
    window_rect_ = stringutils::toRect(jo["windowRect"].toString());
    // Cache dir
    QString s = jo["cacheDir"].toString().trimmed();
    if (s.isEmpty() || s.startsWith('.')) {
        cache_dir_ = rootDir();
    } else {
        QDir dir(s);
        cache_dir_ = dir.exists() ? dir : rootDir();
    }
    // Access dir
    s = jo["lastAccessDir"].toString().trimmed();
    if (!s.isEmpty() && !s.startsWith('.')) {
        const QDir dir { s };
        if (dir.exists()) {
            access_dir_ = dir;
        }
    }
    // Recorder
    const auto jo_rs = jo["recorderSettings"].toObject();
    if (!jo_rs.isEmpty()) {
        recorder_settings_ = RecorderSettings::fromJSONObject(jo_rs);
        if (recorder_settings_.video_save_dir.isEmpty()
            || recorder_settings_.video_save_dir.startsWith('.')) {
            recorder_settings_.video_save_dir =
                    utils::createDirectoryInNonSystemDrive("YingceVideos");
        }
    } else {
        recorder_settings_.video_save_dir = utils::createDirectoryInNonSystemDrive("YingceVideos");
        qint64 total_memory = utils::getTotalSystemMemory();
        if (total_memory > 0) {
            constexpr qint64 memory_threshold = 2LL * Constants::GB; // 4GB in bytes
            recorder_settings_.realtime_monitor_count =
                    static_cast<int>(total_memory / memory_threshold);
            recorder_settings_.regular_monitor_count =
                    static_cast<int>(total_memory / memory_threshold);
        }
    }
    new_recorder_settings_ = recorder_settings_;
    // ScreenCapture
    const auto jo_scs = jo["screenCaptureSettings"].toObject();
    if (!jo_scs.isEmpty()) {
        screen_capture_settings_ = ScreenCaptureSettings::fromJSONObject(jo_scs);
        if (screen_capture_settings_.save_dir.isEmpty()
            || screen_capture_settings_.save_dir.startsWith('.'))
            screen_capture_settings_.save_dir =
                    utils::createDirectoryInNonSystemDrive("YingceScreenVideos");
    } else {
        screen_capture_settings_.save_dir =
                utils::createDirectoryInNonSystemDrive("YingceScreenVideos");
    }
    // web debug enabled
    web_debug_enabled_ = jo["webDebugEnabled"].toBool(false);
}

void UserSettings::save()
{
    QFile file(rootDir().absoluteFilePath("yingce.dat"));
    if (file.open(QFile::WriteOnly | QFile::Truncate)) {
        QJsonObject jo;
        jo["version"] = VERSION_NUMBER;
        jo["disclaimerAccepted"] = disclaimer_accepted_;
        // Updater
        jo["ignoreMajorVersion"] = ignore_major_version_;
        jo["ignoreUpdateDate"] = ignore_update_date_;
        // Window state
        jo["windowState"] = window_state_;
        jo["windowRect"] = stringutils::toString(window_rect_);
        // Access dir
        jo["lastAccessDir"] = access_dir_.absolutePath();
        // Login user
        jo["lastLoginUser"] = login_user_.toJsonObject();
        // Cache dir
        if (new_cache_dir_ != QDir() && new_cache_dir_.exists()) {
            if (new_cache_dir_ != rootDir()) {
                jo["cacheDir"] = new_cache_dir_.absolutePath();
            }
        } else {
            if (cache_dir_ != rootDir()) {
                jo["cacheDir"] = cache_dir_.absolutePath();
            }
        }
        // Recorder
        jo["recorderSettings"] = new_recorder_settings_.toJSONObject();
        // ScreenCapture
        jo["screenCaptureSettings"] = screen_capture_settings_.toJSONObject();

        file.write(QJsonDocument(jo).toJson(QJsonDocument::Compact));
        file.close();
    }
}

QDir UserSettings::rootDir()
{
    QDir dir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
    if (!dir.exists("yingce")) {
        dir.mkpath("yingce");
    }
    dir.cd("yingce");
    return dir;
}

QDir UserSettings::logDir()
{
    QDir dir(rootDir());
    if (dir.exists("log") || dir.mkdir("log")) {
        dir.cd("log");
        return dir;
    } else {
        return QDir::temp();
    }
}

QDir UserSettings::webCacheDir()
{
    QDir dir(rootDir());
    if (dir.exists("webcache") || dir.mkdir("webcache")) {
        dir.cd("webcache");
        return dir;
    } else {
        return QDir::temp();
    }
}
